﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Globalization;

namespace client
{
    public delegate void TextUpdate(object sender, double value);
    public partial class FineCourseEdit : TextBox
    {
        public enum StepMode
        {
            StepAdd,
            StepMult
        }

        public enum StepDir
        {
            StepUp,
            StepDown
        }

        private const int WM_KEYDOWN = 0x100;
        private const int WM_SYSKEYDOWN = 0x104;
        private const int VK_DOWN = 0x0028;
        private const int VK_UP = 0x0026;
        private const int VK_NEXT = 0x0022;
        private const int VK_PRIOR = 0x0021;
        private const int VK_ENTER = 0x000D;

        public double MaxValue = 100;
        public double MinValue = 0;

        public string Format = "g";
        public StepMode FineMode = StepMode.StepAdd;
        public double FineStep = 10;

        public StepMode CourseMode = StepMode.StepAdd;
        public double CourseStep = 100;

        public event TextUpdate TextUpdate;

        public FineCourseEdit()
        {
            AcceptsReturn = true;

            Leave += new EventHandler(OnLeave);
        }

        public void SetFine(StepMode mode, double step)
        {
            FineMode = mode;
            FineStep = step;
        }

        public void SetCourse(StepMode mode, double step)
        {
            CourseMode = mode;
            CourseStep = step;
        }

        public double Value
        {
            get { return ParseDouble(Text); }
            set { SetValue(value); }
        }

        public void SetValue(double value)
        {
            value = value < MinValue ? MinValue : value > MaxValue ? MaxValue : value;
            Text = value.ToString(Format);
        }

        private double ParseDouble(string value)
        {
            string dotValue = value.Replace(',', '.');
            try
            {
                return double.Parse(dotValue == "" ? "0" : dotValue, CultureInfo.InvariantCulture);
            }
            catch
            {
                return 0;
            }
        }

        private void UpdateValue(StepMode mode, StepDir dir, double step)
        {
            double value = ParseDouble(Text);

            switch (mode)
            {
                case StepMode.StepAdd: if (dir == StepDir.StepUp) value += step; else value -= step; break;
                case StepMode.StepMult: if (dir == StepDir.StepUp) value *= step; else value /= step; break;
            }

            value = value < MinValue ? MinValue : value > MaxValue ? MaxValue : value;

            SetValue(value);

            if (TextUpdate != null)
                TextUpdate(this, value);
        }

        private void OnLeave(object sender, EventArgs e)
        {
            UpdateValue(StepMode.StepAdd, StepDir.StepUp, 0);
        }

        protected override void WndProc(ref Message m)
        {
            if (m.Msg == WM_KEYDOWN || m.Msg == WM_SYSKEYDOWN)
            {
                switch ((int)m.WParam)
                {
                    case VK_ENTER:
                        UpdateValue(StepMode.StepAdd, StepDir.StepUp, 0); break;
                    case VK_PRIOR:
                        UpdateValue(CourseMode, StepDir.StepUp, CourseStep); break;
                    case VK_UP:
                        UpdateValue(FineMode, StepDir.StepUp, FineStep); break;
                    case VK_DOWN:
                        UpdateValue(FineMode, StepDir.StepDown, FineStep); break;
                    case VK_NEXT:
                        UpdateValue(CourseMode, StepDir.StepDown, CourseStep); break;
                    default:
                        base.WndProc(ref m);
                        break;
                }
            }
            else
                base.WndProc(ref m);
        }
    }
}
